﻿//
// Created by Administrator on 2022/6/15.
//

#include "MainApp.h"
// wxWidgets
#include "wx/wx.h"
#include "wx/confbase.h"
#include "wx/stdpaths.h"
#include "wx/sysopt.h"
#include <wx/fs_zip.h> // ZIP filesystem support
#include <wx/tipdlg.h>
#include <wx/cshelp.h>
#include <wx/image.h>

#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/locale.hpp>

#include "MainApp.h"
#include "MainDialog.h"

#define APPLICATION_NAME "Repository"
static const wxChar HELP_FILE[] =  wxT ( "/Resources/HelpFile" );

#ifdef USE_STARTUP_TIPS
static const wxChar TIPS_FILE[] = wxT ( "/Resources/TipsFile" );
static const wxChar TIPS_SHOW_AT_STARTUP[] = wxT ( "/Main/TipsShowAtStartup" );
static const wxChar TIPS_LAST_INDEX[] = wxT ( "/Main/TipsLastIndex" );
#endif

IMPLEMENT_APP ( MainApp )

#define key_remote_mysql_ip "remote-mysql-ip"
#define key_remote_mysql_port "remote-mysql-port"
#define key_mysql_user "mysql-user"
#define key_mysql_password "mysql-password"
#define key_mysql_database "mysql-database"

#define key_remote_ssh_ip "remote-ssh-ip"
#define key_remote_ssh_port "remote-ssh-port"
#define key_ssh_user "ssh-user"
#define key_ssh_password "ssh-password"
#define key_ssh_remote_path "ssh-remote-path"

#define key_log_to_file "log-to-file"
#define key_log_filename "log-filename"
#define key_remove_after_copy "remove-after-copy"

/*
 * if(tag_system.count( key_log_to_file ) != 1) {
        std::cerr << ConvertTitle( key_log_to_file )
                  <<" node not exists." << std::endl;
        exit(-1);
    }
    log_filename = tag_system.get<bool>( key_log_to_file );
    std::cout << ConvertTitle( key_log_to_file )
              <<": " << log_filename << std::endl;
    to macro
 */
#define have_key
string remote_mysql_ip;
int  remote_mysql_port;
string mysql_user;
string mysql_password;
string mysql_database;

string remote_ssh_ip;
int  remote_ssh_port;
string ssh_user;
string ssh_password;
string ssh_remote_path;

bool log_to_file;
string log_filename;

static string ConvertTitle(string key ) {
    string::size_type position = key.find("_");
    while (position != key.npos) {
        key = key.replace(key.find("_"), 1, "-");
        position = key.find("_");
    }
    return key;
}

static const wxCmdLineEntryDesc cmdLineDesc[] =
        {
                { wxCMD_LINE_SWITCH, "h", "help",
                  "show this help message",
                  wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP },
                { wxCMD_LINE_SWITCH, "s", "secret",
                  "a secret switch",
                  wxCMD_LINE_VAL_NONE, wxCMD_LINE_HIDDEN },
                // ... your other command line options here...
                { wxCMD_LINE_SWITCH, "l", "list",
                  "process a file list",
                  wxCMD_LINE_VAL_STRING, 0 },
                { wxCMD_LINE_SWITCH, "f", "file",
                  "process a file",
                  wxCMD_LINE_VAL_STRING, 0 },
                { wxCMD_LINE_SWITCH, "d", "dir",
                  "process a dir",
                  wxCMD_LINE_VAL_STRING, 0 },
                //{ wxCMD_LINE_OPTION, ("d"), ("debug"), ("specify a debug level") },
                { wxCMD_LINE_SWITCH, "D", "delete",
                  "remove file after post",
                  wxCMD_LINE_VAL_STRING, 0 },
                { wxCMD_LINE_PARAM,  nullptr, nullptr, ("input file"),
                  wxCMD_LINE_VAL_STRING,
                  wxCMD_LINE_PARAM_OPTIONAL },
                wxCMD_LINE_DESC_END
        };

/*
 *
 */
bool MainApp::OnInit()
{
    //https://blog.csdn.net/wyansai/article/details/78473994
    m_checker = new wxSingleInstanceChecker();
    if (m_checker->IsAnotherRunning()) {
        delete m_checker;
        m_checker = nullptr;
        return false;
    }

    if( argc!=2 ){
        wxFprintf( stderr, "USAGE: %s config file path", argv[0] );
        exit(-1);
    }
    //parse the config file
    if (!wxFile::Exists( argv[1] )) {
        std::cerr << "config file not exists." << std::endl;
        exit(-1);
    }
    boost::property_tree::ptree root_node, tag_system;
    boost::property_tree::ini_parser::read_ini( argv[1].ToStdString(),
                                               root_node);
    tag_system = root_node.get_child("main");
    //
    if(tag_system.count( key_remote_mysql_ip ) != 1) {
        std::cerr << ConvertTitle(key_remote_mysql_ip)
                << " node not exists." << std::endl;
        exit(-1);
    }
    remote_mysql_ip = tag_system.get<string>( key_remote_mysql_ip );
    std::cout << ConvertTitle(key_remote_mysql_ip)
                <<": " << remote_mysql_ip << std::endl;

    if(tag_system.count( key_remote_mysql_port ) != 1) {
        std::cerr << ConvertTitle( key_remote_mysql_port )
                <<" node not exists." << std::endl;
        exit(-1);
    }
    //ignore check the port format: port format
    remote_mysql_port = tag_system.get<int>( key_remote_mysql_port );
    std::cout << ConvertTitle(key_remote_mysql_port)
                <<": " << remote_mysql_port << std::endl;

    if(tag_system.count( key_mysql_user ) != 1) {
        std::cerr << ConvertTitle( key_mysql_user )
                <<" node not exists." << std::endl;
        exit(-1);
    }
    mysql_user = tag_system.get<string>( key_mysql_user );
    std::cout << ConvertTitle( key_mysql_user )
            <<": " << mysql_user << std::endl;

    if(tag_system.count(key_mysql_password) != 1) {
        std::cerr << ConvertTitle( key_mysql_password )
                <<"node not exists." << std::endl;
        exit(-1);
    }
    mysql_password = tag_system.get<string>( key_mysql_password );
    std::cout << ConvertTitle( key_mysql_password )<<": "
            << mysql_password << std::endl;

    if(tag_system.count(key_mysql_database) != 1) {
        std::cerr << ConvertTitle( key_mysql_database )
                  <<"node not exists." << std::endl;
        exit(-1);
    }

    mysql_database = tag_system.get<string>( key_mysql_database );
    std::cout << ConvertTitle( key_mysql_database )<<": "
              << mysql_database << std::endl;

    //////////////////////////////////////////////
    if(tag_system.count( key_remote_ssh_ip ) != 1) {
        std::cerr << ConvertTitle( key_remote_ssh_ip )
            <<" node not exists." << std::endl;
        exit(-1);
    }
    remote_ssh_ip = tag_system.get<string>("remote-ssh-ip");
    std::cout << ConvertTitle( key_remote_ssh_ip )
            <<": " << remote_ssh_ip << std::endl;

    if(tag_system.count( key_remote_ssh_port ) != 1) {
        std::cerr << ConvertTitle( key_remote_ssh_port )
                <<" node not exists." << std::endl;
        exit(-1);
    }
    //ignore check the port format: port format
    remote_ssh_port = tag_system.get<int>(key_remote_ssh_port );
    std::cout << ConvertTitle( key_remote_ssh_port )
            <<": " << remote_ssh_port << std::endl;

    if(tag_system.count(key_ssh_user ) != 1) {
        std::cerr << ConvertTitle( key_ssh_user )
            <<" node not exists." << std::endl;
        exit(-1);
    }
    ssh_user = tag_system.get<string>("ssh-user");
    std::cout << ConvertTitle( key_ssh_user )
            <<": " << ssh_user << std::endl;

    if(tag_system.count(key_ssh_password) != 1) {
        std::cerr << ConvertTitle( key_ssh_password )
                <<" node not exists." << std::endl;
        exit(-1);
    }
    ssh_password = tag_system.get<string>(key_ssh_password );
    std::cout << ConvertTitle( key_ssh_password )
                <<": " << ssh_password << std::endl;

    if(tag_system.count(key_ssh_remote_path) != 1) {
        std::cerr << ConvertTitle( key_ssh_remote_path )
                  <<"node not exists." << std::endl;
        exit(-1);
    }

    ssh_remote_path = tag_system.get<string>( key_ssh_remote_path );
    std::cout << ConvertTitle( key_ssh_remote_path )<<": "
              << ssh_remote_path << std::endl;
    ////////////////////////////////////////
    if(tag_system.count( key_log_filename ) != 1) {
        std::cerr << ConvertTitle( key_log_filename )
            <<" node not exists." << std::endl;
        exit(-1);
    }

    log_filename = tag_system.get<string>( key_log_filename );
    std::cout << ConvertTitle( key_log_filename )
            <<": " << log_filename << std::endl;

    if(tag_system.count( key_log_to_file ) != 1) {
        std::cerr << ConvertTitle( key_log_to_file )
                  <<" node not exists." << std::endl;
        exit(-1);
    }

    log_to_file = tag_system.get<bool>( key_log_to_file );
    std::cout << ConvertTitle( key_log_to_file )
              <<": " << log_to_file << std::endl;

    //
    fileName = nullptr;
    deleted = log_to_file;
    // 分析命令行
    wxString cmdFilename;
    wxCmdLineParser cmdParser( cmdLineDesc, argc, argv);
    int res;

    wxLogNull log;
    // 传递False参数以便在分析命名行发生错误的时候不显示使用帮助对话框.
    res = cmdParser.Parse(false);
    // 检查是否用户正在询问使用帮助
    switch (cmdParser.Parse()) {
        case -1:
            break;
        case 0:
            if (cmdParser.Found("f")) {
                wxString cmdFilename = cmdParser.GetParam(0);
                cmdFilename.Replace("\\", "/");
                fileName = new wxFileName( cmdFilename );
                fileName->Normalize(wxPATH_NORM_LONG|wxPATH_NORM_DOTS|
                                    wxPATH_NORM_TILDE|wxPATH_NORM_ABSOLUTE);
            }
            if (cmdParser.Found("D")) {
                wxString Delete = cmdParser.GetParam(0);
                if( Delete.IsSameAs("y") )
                    deleted = true;
                else
                    deleted = false;
            }
            break;
        default:
            break;
    };

    /*
    if ( cmdParser.GetParamCount() != 0 )
    {
        //wxPrintf("Welcome to the wxWidgets 'console' sample!\n");
        wxString cmdFilename = cmdParser.GetParam(0);
        cmdFilename.Replace("\\", "/");
        //wxMessageBox( cmdFilename, "文件名" );
        //wxPrintf( cmdFilename );
        fileName = new wxFileName( cmdFilename );
        //wxMessageBox( fileName->GetFullPath(), "文件名" );
        fileName->Normalize(wxPATH_NORM_LONG|wxPATH_NORM_DOTS|
                            wxPATH_NORM_TILDE|wxPATH_NORM_ABSOLUTE);
    }
    */
    // application and vendor name are used by wxConfig to construct the name
    // of the config file/registry key and must be set before the first call
    // to Get() if you want to override the default values (the application
    // name is the name of the executable and the vendor name is the same)
    SetVendorName ( APPLICATION_NAME );
    SetAppName ( APPLICATION_NAME );

    m_locale.Init();
    wxLocale::AddCatalogLookupPathPrefix ( wxT ( "locale" ) );
#ifdef __WXMAC__
    wxSystemOptions::SetOption ( wxT ( "mac.listctrl.always_use_generic" ), true );
	m_locale.AddCatalogLookupPathPrefix (
	    wxStandardPaths::Get().GetResourcesDir() +
	    wxFileName::GetPathSeparator() +
	    wxT ( "locale" ) );
#endif //__WXMAC__
	//?
    m_locale.AddCatalog ( wxT ( "Repository" ) );

    // Add support for PNG
    wxImage::AddHandler ( new wxPNGHandler );

#ifdef _WIN32
    // Avoiding to conflict with different versioned apr-iconv.
    wxString apr_iconv_path;
    if ( wxGetEnv ( wxT ( "APR_ICONV_PATH" ), &apr_iconv_path ) ) {
        wxSetEnv ( wxT ( "__SAVED_APR_ICONV_PATH" ), apr_iconv_path.c_str() );
        wxSetEnv ( wxT ( "APR_ICONV_PATH" ), wxStandardPaths::Get().GetDataDir()
        + wxT ( "\\iconv" ) );
    }
#endif

#ifdef  USE_HTML_HELP
    // Initialise the HTML help
	wxFileSystem::AddHandler ( new wxZipFSHandler );
	m_helpController = new wxHtmlHelpController;
	m_helpController->SetTitleFormat ( _ ( "RapidSVN Help: %s" ) );
	LocateHelp();

	// Initialise a popup-help-text provider system, connected to the main help system
	wxHelpControllerHelpProvider* provider = new wxHelpControllerHelpProvider;
	provider->SetHelpController ( m_helpController );
#else
    auto* provider = new wxSimpleHelpProvider;
#endif
    wxHelpProvider::Set ( provider );
    //
    auto * frame = new MainDialog (  );
    frame->Show ( TRUE );
    SetTopWindow ( frame );

    // Show tips if configured
#ifdef USE_STARTUP_TIPS
    wxTipProvider* tipProvider = MakeTipProvider();
	if ( tipProvider ) {
		bool showAtStartup = wxShowTip ( frame, tipProvider );
		SaveTipsInfo ( showAtStartup, tipProvider->GetCurrentTip() );
		delete tipProvider;
	}
#endif

    return TRUE;
}

int MainApp::OnExit()
{
    delete wxConfigBase::Set ( ( wxConfigBase * ) nullptr );

    // Remove the help provider & close down help
    delete wxHelpProvider::Set ( nullptr );

    if( fileName )
        delete fileName;
    return 0;
}
